package nio.nio;



import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * @author 帅小伙
 * @date 2022/1/14
 * @description
 * NIO的服务端
 */
public class NIOServer {

    public static void main(String[] args) throws Exception {

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        //到一个selector对象
        Selector selector = Selector.open();

        // 绑定一个端口6666  在服务器监听
        serverSocketChannel.socket().bind(new InetSocketAddress(6666));
        // 设置成非阻塞
        serverSocketChannel.configureBlocking(false);

        // 把serverSocketChannel  注册到 selector  关心事件为  OP_ACCEPT
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 循环等待客户端连接   selector开始监听
        while(true){

            // 等待1s    如果没有事件发生    返回
            if(selector.select(1000) == 0){
                System.out.println("服务器等待1s  无连接");
                continue;
            }

            // 如果返回>0  获取相关的selectionKey集合
            // 1,如果返回>0  获得关注的事件
            // 2. selectedKeys  关注事件的集合
            //     通过selectionKeys   反向获取通道
            Set<SelectionKey> selectionKeys = selector.selectedKeys();

            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();

            while(keyIterator.hasNext()) {
                // 获取 selectorKey
                SelectionKey key = keyIterator.next();
                // 获取key对应的通道  做相应的处理
                if(key.isAcceptable()){  // 有客户端连接我
                    //该客户端生成一个SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println("客户端连接成功 生成一个socketChannel "+ socketChannel.hashCode());
                    socketChannel.configureBlocking(false);
                    // 将当前channel注册到selector  关注事件 读    同时关联一个  buffer
                    socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));

                }
                if(key.isReadable()){ //发生读事件
                    //反向获取  channel
                    SocketChannel channel = (SocketChannel)key.channel();
                    // 获取到该channel关联的buffer
                    ByteBuffer buffer = (ByteBuffer)key.attachment();
                    channel.read(buffer);
                    System.out.println("客户端"+new String(buffer.array()));
                }

                // 手动从集合中移除当前的selectionKey   多线程 防止重复操作
                keyIterator.remove();
            }

        }


    }
}
